/**
* 这是一个用于网页上传之前对图片处理的工具库
* @author : marlondu
* zipper.init({		//zipper对象初始化
*	inputFileId:"", //文件输入元素的ID，必须
*	imgId:"",		//用于显示的img元素的ID，必须
*	compress:true,	//是否压缩图片，默认为false
*	compressRate:,	//压缩率[0-1],默认为0.5
*	imgAreaId:"",	//用于显示图片的img元素的父级元素ID,用于控制显示区域的大小
*	proWidth:,		//预设img元素的宽度
*	proHeight:,		//预设Img元素的高度
*   maxSize:,		//选取文件的最大体积，单位byte
* });
* zipper.compressFile();//图片压缩
* zipper.slice(..);		//图片剪裁
* zipper.check(func);	//图片检测
* zipper.sendFile(..);	//向服务器发送
*/
;var zipper = {};
(function(zipper){
	
	var inputfile_ele = {};
	var img_ele = {};
	var name = "";			//选择的图片的文件名
	var size = 0;			//选取的图片的大小(字节数)
	var showWidth = 0;		//图片显示的宽度
	var showHeight = 0;		//图片显示的高度
	var reader = new FileReader();
	var type = "default";	//选取的图片的类型
	var proWidth = 300;		//img元素的预设宽度
	var proHeight = 400;	//img元素的预设高度
	var imgObj = {};		//图片File对象
	var compress = false;	//是否压缩
	var compressRate = 0.5;	//压缩率
	var resImg = document.createElement("img");//手动创建的img元素，用于储存图片的原始信息
	var blob = null;		//要发送的文件的Blob对象
	var maxSize = 0;		//选取文件的最大体积，单位byte
	/**
	* 初始化方法
	*/
	var initial = function(args){
		//获取<input type="file"/>DOM对象
		if(args.inputFileId) inputfile_ele = document.getElementById(args.inputFileId);
		else return false;
		//获取<img src=""/>DOM对象
		if(args.imgId) img_ele = document.getElementById(args.imgId);
		else return false;
		if(args.imgAreaId){
			var div_width = document.getElementById(args.imgAreaId).style.width;
			var div_height = document.getElementById(args.imgAreaId).style.height;
			if(div_height&&div_width){
				div_width = div_width.substring(0,div_width.indexOf("p"));
				div_height = div_height.substring(0,div_height.indexOf("p"));
				proWidth = parseInt(div_width);
				proHeight = parseInt(div_height);
			}
		}
		if(args.proWidth) proWidth = args.proWidth;
		if(args.proHeight) proHeight = args.proHeight;
		if(args.compress) compress = args.compress;
		if(args.compressRate) compressRate = args.compressRate;
		if(args.maxSize) maxSize = args.maxSize;
		return true;
	}
	var clearVal = function(){
		inputfile_ele.value = "";
		reader.onload = null;
		imgObj = null;
		type = "default";
		name = "";
		size = 0;
	}
	/**
	* 调用入口，用户通过调用此方法，为程序指定所需参数
	*/
	zipper.init = function(options){
		if(initial(options)){
			registerFileChange();
		}
		return this;
	}
	/**
	* 给input File元素注册onchange事件处理
	*/
	var registerFileChange  = function(){
		if(inputfile_ele){
			inputfile_ele.onchange = function(){
				//获取图片文件对象
				imgObj = this.files[0];
				size = imgObj.size;
				name = imgObj.name;
				type = imgObj.type;
				blob = imgObj;
				//如果文件类型是图片
				if(/image/.test(type)){
					reader.readAsDataURL(imgObj);
					
				}else{
					alert("您选择的不是图片啊");
					return;
				}
				if(maxSize>0 && size>maxSize){
					clearVal();
					return;
				}
				reader.onload = function(){
					resImg.src = this.result;
					img_ele.src = this.result;
					img_ele.width = 0;
					img_ele.height = 0;
				}
				reader.onerror = function(){
					console.log("读取文件出现异常！");
				}
			}
			resImg.onload = function(){
				img_ele.width = resImg.width;
				img_ele.height = resImg.height;
				if(compress){
					compressFile(compressRate);	
				}
				calcShowSize();
				
			}
			img_ele.onload = function(){}
		}
	}
	/**
	* 将选择的图片压缩并显示到img元素上
	* @rate 压缩率[>0]
	*/
	zipper.compressFile = function(rate){
		if(rate<=0||isNaN(rate)){
			console.log("压缩率："+rate+" 不合法！");
			return false;
		}
		var drawing = document.createElement("canvas");
		drawing.width = resImg.width*rate;
		drawing.height = resImg.height*rate;
		if(drawing.getContext){
			var context = drawing.getContext("2d");
			/**
			* context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
			* img 	规定要使用的图像、画布或视频。
			* sx	可选。开始剪切的 x 坐标位置。
			* sy 	可选。开始剪切的 y 坐标位置。
			* swidth可选。被剪切图像的宽度。
			* sheight可选。被剪切图像的高度。
			* x		在画布上放置图像的 x 坐标位置。
			* y 	在画布上放置图像的 y 坐标位置。
			* width	可选。要使用的图像的宽度（伸展或缩小图像）。
			* height可选。要使用的图像的高度（伸展或缩小图像）。
			*/
			context.drawImage(resImg,0,0,resImg.width,resImg.height,0,0,drawing.width,drawing.height);
			var imgURL = drawing.toDataURL(type);
			size = size*rate*rate;
			console.log("压缩后size-->"+size);
			//将压缩后的图片显示在目标img上
			console.log(resImg.width+"----原长宽---"+resImg.height);
			img_ele.width = drawing.width;
			img_ele.height = drawing.height;
			console.log(img_ele.width+"----压缩后---"+img_ele.height);
			img_ele.src = imgURL;
			calcShowSize();
			console.log("压缩成功！");
			blob = toBlob(img_ele.src);
			size = blob.size;
		}else{
			console.log("很抱歉，您的浏览器不支持此技术！");
		}
		return this;
	}
	/**
	* btoa() 将字符串转化为base64编码
	* atob() 将base64编码字符串解码
	*/
	var toBlob = function(dataURL){
		var contentType = dataURL.substring(dataURL.indexOf(":")+1,dataURL.indexOf(";"));
		var base64Str = dataURL.substring(dataURL.indexOf(",")+1);
		var byteCharacters = atob(base64Str);//decode a base64-decoded string into a new string with a charater for each byte of the binary data
		var byteNumbers = new Array(byteCharacters.length);
		for(var i=0;i<byteCharacters.length;i++){
			byteNumbers[i] = byteCharacters.charCodeAt(i);//获取每一个字符的ASCII编码值
		}
		var byteArray = new Uint8Array(byteNumbers);
		var blob = new Blob([byteArray],{type:contentType});
		console.log(blob.type+"----"+blob.size);
		return blob;
	}
	/**
	* 检测页面显示的img元素中的图片的体积，获取他
	* @func function(blob):blob表示图片文件对象，它包含size,type属性 
	*/
	zipper.check = function(func){
		if(typeof func == "function"){
			func(blob);
		}
	}
	/**
	* 将文件发送到指定的url
	* url:"",				要发送的url,必须
	* param_file:"",		指定的file文件的参数名，用于在服务端接收，默认为"file"
	* param_fileName:"",	指定的file文件名的参数名，用于在服务端接收，默认为"fileName"
	* 
	*/
	zipper.sendFile = function(options){
		if(blob == null){
			alert("请选择文件");
			return;
		}
		var type = "post";
		var url = "";
		if(options.url) url = options.url;
		else return;
		var param_file = options.param_file || "file";
		var param_fileName = options.param_fileName || "fileName";
		var fileName = makeFileName(name);
		var fd = new FormData();
		fd.append(param_file,blob);
		fd.append(param_fileName,fileName);
		fd.append("contentType",type);
		var xhr = createXHR();
		/**
		* 上传进度事件，可通过progress自定义({progress:function(){},});
		*/
		xhr.onprogress = function(event){
			if(options.progress&& typeof options.progress == "function"){
				if (event.lengthComputable){
					options.progress(event.position,event.totalSize);
				}
			}else{
				if (event.lengthComputable){
					console.log("进度-"+event.position+"/"+event.totalSize+"-");
				}
			}
		}
		/**
		* 上传错误事件，可通过error自定义({error:function(){},});
		*/
		xhr.onerror = function(){
			if(options.error&&typeof options.error == "function"){
				options.error();
			}else{
				console.log("upload error: ")
			}
		}
		xhr.open(type,url,true);
		xhr.onload = function(event){
			if( (xhr.status >= 200 && xhr.status <=300)|| xhr.status == 304){
				if(options.load && typeof options.load == "function"){
					options.load(event.responseText);
				}
				console.log(xhr.status);
			}else{
				console.log("upload unsuccessful: " + xhr.status);
			}
		}
		/**
		* 上传完成事件，可通过complete自定义({complete:function(){},});
		*/
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				if(options.complete&&typeof options.complete == "function"){
					options.complete();
				}else{
					console.log("上传完成！");
				}
			}
		}
		/**
		* 上传超时事件
		* 设置超时时间time后，可通过timeout自定义({timeout:function(){},});
		*/
		if(options.time && options.timeout && 
			typeof options.timeout == "function"){
				xhr.ontimeout = options.timeout;
			}
		xhr.send(fd);
	}
	/**
	* 构造文件名
	*/
	var makeFileName = function(nm){
		var dot = nm.lastIndexOf(".");
		var firstName = nm.substring(0,dot);
		var lastName = nm.substring(dot);
		var d = new Date();
		var dateString = d.toLocaleDateString().replace(/\//g,"");
		var timeString = d.getHours() + "" + d.getMinutes() + "" + d.getSeconds();
		nm = firstName + "_" + dateString+timeString + lastName;
		return nm;
	}
	/**
	* 创建XMLHttpRequest对象
	*/
	var createXHR = function(){
		if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
			return new XMLHttpRequest();
		}else{// code for IE6, IE5
			return new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	/**
	* 计算图片显示的大小
	*/
	var calcShowSize = function(){
		if(img_ele.height<=proHeight&&img_ele.width<=proWidth){
			showHeight = img_ele.height;
			showWidth = img_ele.width;
		}else if(img_ele.height>=proHeight&&img_ele.width<=proWidth){
			var percent = proHeight/img_ele.height;
			showHeight = proHeight;
			showWidth = img_ele.width*percent;
		}else if(img_ele.height<=proHeight&&img_ele.width>=proWidth){
			var percent = proWidth/img_ele.width;
			showWidth = proWidth;
			showHeight = img_ele.height*percent;
		}if(img_ele.height>proHeight&&img_ele.width>proWidth){
			var proPercent = proWidth/proHeight;
			var oriPercent = img_ele.width/img_ele.height;
			if(proPercent>oriPercent){//预设太宽，高度占满
				showHeight = proHeight;
				showWidth = showHeight*oriPercent;
			}else{
				showWidth = proWidth;
				showHeight = showWidth/oriPercent;
			}
			
		}
		showHeight = parseInt(showHeight);
		showWidth = parseInt(showWidth);
		img_ele.width = showWidth;
		img_ele.height = showHeight;
	}
	/**
	* 对图片进行剪裁
	* x 	剪裁开始的左上角的x坐标，必填
	* y 	剪裁开始的右上角的y坐标，必填
	* width 要剪裁的宽度，必填
	* height要剪裁的高度，必填
	* original 默认为false,表示剪裁的是页面上img元素，设为true,则表示剪裁的对对象为原图像
	* 注意默认剪裁的对象是页面img元素(可能是压缩后的)
	*/
	zipper.slice = function(x,y,width,height,original){
		var img_to_slice = img_ele;
		if(original){
			img_to_slice = resImg;
		}
		var drawing = document.createElement("canvas");
		console.log("剪裁前："+img_to_slice.width+"/"+img_to_slice.height);
		drawing.width =  width;
		drawing.height = height;
		if(drawing.getContext){
			var context = drawing.getContext("2d");
			try{
				context.fillStyle="#fff";//为画布填充为白色
				context.fillRect(0,0,width,height);
				context.drawImage(img_to_slice,x,y,width,height,0,0,width,height);
				var imgURL = drawing.toDataURL(type);
				img_ele.width = drawing.width;
				img_ele.height = drawing.height;
				img_ele.src = imgURL;
				console.log("剪裁后："+img_ele.width+"/"+img_ele.height);
				blob = toBlob(img_ele.src);
				size = blob.size;
			}catch(e){
				console.log(e);
			}
		}
		return this;
	}
})(zipper);